#include "imprime_ASA.h"
#include<stdio.h>
#include "analex.h"


ImprimeASA::ImprimeASA(){
    tabulacao = 0;
}
void ImprimeASA::imprimeTabulacao(){
     for(int n=0; n<tabulacao; n++) {
         fprintf(stdout,"  ");
     }
}
void ImprimeASA::visitar(_Program *v){
    if (v != NULL){
        fprintf(stdout, "\n***********ARVORE DE SINTAXE ABSTRATA**********\n");
        fprintf(stdout, "_Program\n");
        tabulacao++;
        if(v->block != NULL) v->block->aceitar(this);
        tabulacao--;
        fprintf(stdout, "\nEOF\n");
    }
}
void ImprimeASA::visitar(_Block *v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Block\n");
        tabulacao++;
        if(v->listadeTipos != NULL) v->listadeTipos->aceitar(this);
        if(v->ListadeVariaveis != NULL) v->ListadeVariaveis->aceitar(this);
        if(v->listadeSubProgramas!= NULL) v->listadeSubProgramas->aceitar(this);
        if(v->listadeStatements != NULL) v->listadeStatements->aceitar(this);
        tabulacao--;
    }
 }



void ImprimeASA::visitar(_SubProgram_List* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_SubProgram_List\n");
        tabulacao++;
        if(v->subprograma != NULL) v->subprograma->aceitar(this);
        if(v->proximo_SubPrograma != NULL) v->proximo_SubPrograma->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_SubPrograma* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_SubPrograma\n");
        tabulacao++;
        if(v->nomeDeclaracao != NULL) v->nomeDeclaracao->aceitar(this);
        if(v->tipoRetorno != NULL) v->tipoRetorno->aceitar(this);
        if(v->parametros != NULL) v->parametros->aceitar(this);
        if(v->bloco_Subprograma != NULL) v->bloco_Subprograma->aceitar(this);
        tabulacao--;
    }
}


void ImprimeASA::visitar(_Var_List* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Var_List\n");
        tabulacao++;
        if(v->nome != NULL) v->nome->aceitar(this);
        if(v->tipo != NULL) v->tipo->aceitar(this);
        if(v->proxima != NULL) v->proxima->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Type* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Type\n");
        tabulacao++;
        if(v->tipo_primitivo != 0){
            imprimeTabulacao();
            fprintf(stdout, "%s\n", retornaNomeToken(v->tipo_primitivo));
        }
        if(v->tipo_personalizado != NULL) v->tipo_personalizado->aceitar(this);
        if(v->numinicio != NULL) v->numinicio->aceitar(this);
        if(v->numfim != NULL) v->numfim->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Type_List* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Type_list\n ");
        tabulacao++;
        if (v->tipo != NULL) v->tipo->aceitar(this);
        if (v->variaveis != NULL) v->variaveis->aceitar(this);
        if (v->proximoTipo != NULL) v->proximoTipo->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Statement_List* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Statement_List\n");
        tabulacao++;
        if(v->statement != NULL) v->statement->aceitar(this);
        if(v->statement_list != NULL) v->statement_list->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Statement *v){}


void ImprimeASA::visitar(_If* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_If\n");
        tabulacao++;
        if(v->expressao != NULL) v->expressao->aceitar(this);
        if(v->statementSe != NULL) v->statementSe->aceitar(this);
        if(v->statementSenao != NULL) v->statementSenao->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_While* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_While\n");
        tabulacao++;
        if (v-> expressao != NULL) v->expressao->aceitar(this);
        if (v-> statementWhile != NULL) v->statementWhile->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Select* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Select\n");
        tabulacao++;
        if (v->expressao != NULL) v->expressao->aceitar(this);
        if (v->caseBlock != NULL) v->caseBlock->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Break* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Break\n");
    }
}

void ImprimeASA::visitar(_Write* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Write\n");
        tabulacao++;
        if (v->listaExpressao != NULL) v->listaExpressao->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Read* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Read\n");
        tabulacao++;
        if (v->listaExpressao != NULL) v->listaExpressao->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_CaseBlock* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_CaseBlock\n");
        tabulacao++;
        if (v->expressao != NULL) v->expressao->aceitar(this);
        if (v->statement_list != NULL) v->statement_list->aceitar(this);
        if (v->caseblock_prox != NULL) v->caseblock_prox->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Exp_List* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Exp_List\n");
        tabulacao++;
        if (v->expressao != NULL) v->expressao->aceitar(this);
        if (v->proxima != NULL) v->proxima->aceitar(this);
        tabulacao--;
    }
}

void ImprimeASA::visitar(_Exp* v){}

void ImprimeASA::visitar(_Assign* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Assign\n");
        tabulacao++;
        if (v->name != NULL) v->name->aceitar(this);
        if (v->expressao != NULL) v->expressao->aceitar(this);
        tabulacao--;
    }
}

_Type* ImprimeASA::visitar(_Name* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Name\n");
        tabulacao++;
        if (v->name1 != NULL) v->name1->aceitar(this);
        if (v->name2 != NULL) v->name2->aceitar(this);
        if (v->id != NULL) v->id->aceitar(this);
        if (v->expressao != NULL) v->expressao->aceitar(this);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_Call* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Call\n");
        tabulacao++;
        if (v->id != NULL) v->id->aceitar(this);
        if (v->exp_List != NULL) v->exp_List->aceitar(this);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_Relational_Op* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Relational_Op\n");
        tabulacao++;
        if (v->op_Rel != 0){
            imprimeTabulacao();
            fprintf(stdout, "%s\n", retornaNomeToken(v->op_Rel));
        }
        if (v->expressao1 != NULL) v->expressao1->aceitar(this);
        if (v->expressao2 != NULL) v->expressao2->aceitar(this);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_Addition_Op* v){
    if (v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Addition_Op\n");
        tabulacao++;
        if(v->op_Add != 0){
            imprimeTabulacao();
            fprintf(stdout, "%s\n", retornaNomeToken(v-> op_Add));
        }
        if(v->expressao1 != NULL) v->expressao1->aceitar(this);
        if(v->expressao2 != NULL) v->expressao2->aceitar(this);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_Multiplication_Op* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Multiplication_Op\n");
        tabulacao++;
        if(v->op_Mult != 0){
            imprimeTabulacao();
            fprintf(stdout, "%s\n", retornaNomeToken(v-> op_Mult));
        }
        if(v-> expressao1 != NULL) v->expressao1->aceitar(this);
        if(v-> expressao2 != NULL) v->expressao2->aceitar(this);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_Boolean_Op* v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Boolean_Op\n");
        tabulacao++;
        if(v->op_Bool != 0){
            imprimeTabulacao();
            fprintf(stdout, "%s\n", retornaNomeToken(v-> op_Bool));
        }
        if (v-> expressao1 != NULL) v->expressao1->aceitar(this);
        if (v-> expressao2 != NULL) v->expressao2->aceitar(this);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_Sign *v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Sign\n");
        tabulacao++;
        if(v->expressao != NULL) v->expressao->aceitar(this);
        tabulacao--;
    }
    return NULL;
}
_Type* ImprimeASA::visitar(_ID *v){
    if(v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_ID");
        tabulacao++;
        if(v->identificador != NULL) fprintf(stdout,".%s\n", v->identificador);
        tabulacao--;
    }
    return NULL;
}
_Type* ImprimeASA::visitar(_Number *v){
    if (v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Number");
        tabulacao++;
        if (v->num != NULL) fprintf(stdout, ".%s\n", v->num);
        tabulacao--;
    }
    return NULL;
}
_Type* ImprimeASA::visitar(_Literal *v){
    if (v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_Literal");
        tabulacao++;
        if(v->literal != NULL) fprintf(stdout, ".%s\n", v->literal);
        tabulacao--;
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_True *v){
    if (v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_True.verdadeiro\n");
    }
    return NULL;
}

_Type* ImprimeASA::visitar(_False *v){
    if (v != NULL){
        imprimeTabulacao();
        fprintf(stdout, "_False.falso\n");
    }
    return NULL;
}

ImprimeASA::~ImprimeASA(){
}


